﻿using System;
using System.Collections.Generic;
using System.Numerics;
using System.Windows;
using System.Windows.Media;
using Fantom;
using FantomUI.Controls;

namespace FantomUI.Util
{
	/// <summary>
	/// 框体帮助类，用于实现框体的扭曲。
	/// </summary>
	public static class FrameHelper
	{

		/// <summary>
		/// 顶点以顺时针表示。
		/// </summary>
		public struct FrameInfo
		{
			public double originLeft, originTop;
			public double width;
			public double height;

			// 选框的八个点的效果。
			public Point point1;
			public Point point12;
			public Point point2;
			public Point point23;
			public Point point3;
			public Point point34;
			public Point point4;
			public Point point41;

			/// <summary>
			/// 锚点。
			/// </summary>
			public Point anchor;

			/// <summary>
			/// 边沿上的交点，用于绘制拖动框。
			/// </summary>
			public Point onEdge;

			/// <summary>
			/// 旋钮的位置。
			/// </summary>
			public Point rotationPos;

			/// <summary>
			/// 角度。
			/// </summary>
			public float rotation;

			/// <summary>
			/// 额外的控制点信息，如调节手柄，PPT的下拉效果。
			/// </summary>
			public double[] extra;

			// 可视化中边缘的点。
			public Point left;
			public Point right;
			public Point top;
			public Point buttom;

		}

		/// <summary>
		/// 将从WPFINFO中的数据转换为解析器能够识别的样式。
		/// </summary>
		/// <param name="wpfInfo"></param>
		/// <returns></returns>
		public static FrameInfo GetFrameInfo(this IShape shape)
		{
			var wpfInfo = shape.Transform.GetWPFRenderTransformInfo();
			var rect = new Rect(wpfInfo.Left, wpfInfo.Top, wpfInfo.Width, wpfInfo.Height);
			var anchor = new Vector2() { X = (float)wpfInfo.AnchorWidth, Y = (float)wpfInfo.AnchorHeight };

			return GetFrameInfo(shape,rect, anchor, (float)wpfInfo.Rotation);
		}

		/// <summary>
		/// 判断图形是否位于选框。
		/// </summary>
		/// <param name="shape"></param>
		/// <param name="rect"></param>
		/// <returns></returns>
		public static bool IsInSelectionFrame(this UIShape shape, Rect rect)
		{
			return rect.Left < shape.FrameInfo.left.X &&
			rect.Right > shape.FrameInfo.right.X &&
			rect.Top < shape.FrameInfo.top.Y &&
			rect.Bottom > shape.FrameInfo.buttom.Y;
		}

		/// <summary>
		/// 判断该图形是否位于选框。
		/// </summary>
		public static bool IsInSelectionFrame(this Fantom.IShape shape, Rect rect)
		{
			var info = shape.GetFrameInfo();
			double left = double.MaxValue, right = 0, top = double.MaxValue, buttom = 0;
			var arr = new[] { info.point1, info.point2, info.point3, info.point4 };

			foreach (var item in arr)
			{
				left = Math.Min(item.X, left);
				right = Math.Max(item.X, right);
				top = Math.Min(item.Y, top);
				buttom = Math.Max(item.Y, buttom);
			}

			return rect.Left < left &&
				rect.Right > right &&
				rect.Top < top &&
				rect.Bottom > buttom;

		}

		/// <summary>
		/// 绘制一个四边形。
		/// </summary>
		public static void DrawRectangle(this DrawingContext render, Brush brush, Pen pen, FrameInfo frameInfo)
		{

			var sg = new StreamGeometry();
			var sgc = sg.Open();

			sgc.BeginFigure(frameInfo.point1, true, true);
			sgc.LineTo(frameInfo.point2, true, false);
			sgc.LineTo(frameInfo.point3, true, false);
			sgc.LineTo(frameInfo.point4, true, false);

			sgc.Close();
			sg.Freeze();
			render.DrawGeometry(brush, pen, sg);

		}

		/// <summary>
		/// 在指定点绘制一个角度旋转的矩形。
		/// </summary>
		public static void DrawRectangle(this DrawingContext render, Brush brush, Pen pen, Point point, double size, double rotation, double roundRadius)
		{
			var rect = new Rect(point.X - size / 2, point.Y - size / 2, size, size);

			render.DrawGeometry(brush, pen,
				new RectangleGeometry(rect, roundRadius, roundRadius,
				new RotateTransform(rotation / Math.PI * 180, point.X, point.Y)));


			//render.DrawRectangle(brush, pen, rect);

		}

		/// <summary>
		/// 求取集合中最左侧的点。
		/// </summary>
		/// <param name="points"></param>
		/// <returns></returns>
		private static Point Left(Point[] points)
		{
			var p = points[0];
			foreach (var point in points)
			{
				if (p.X > point.X)
					p = point;
			}
			return p;
		}


		/// <summary>
		/// 求取集合中最右侧的点。
		/// </summary>
		/// <param name="points"></param>
		/// <returns></returns>
		private static Point Right(Point[] points)
		{
			var p = points[0];
			foreach (var point in points)
			{
				if (p.X < point.X)
					p = point;
			}
			return p;
		}

		/// <summary>
		/// 求取集合中最顶侧的点。
		/// </summary>
		/// <param name="points"></param>
		/// <returns></returns>
		private static Point Top(Point[] points)
		{
			var p = points[0];
			foreach (var point in points)
			{
				if (p.Y > point.Y)
					p = point;
			}
			return p;
		}

		/// <summary>
		/// 求取集合中最底侧的点。
		/// </summary>
		/// <param name="points"></param>
		/// <returns></returns>
		private static Point Buttom(Point[] points)
		{
			var p = points[0];
			foreach (var point in points)
			{
				if (p.Y < point.Y)
					p = point;
			}
			return p;
		}


		/// <summary>
		/// 获得整个基本矩形框的全部控点信息。
		/// </summary>
		public static FrameInfo GetFrameInfo(IShape shape,Rect rect, Vector2 anchor, float rotation)
		{
			var distance = RotationThumbVisual.Distance;
			Point point1;
			Point point12;
			Point point2;
			Point point23;
			Point point3;
			Point point34;
			Point point4;
			Point point41;

			Point anchorPos;

			Point onEdge;

			Point rotationPos;

			var extra = new List<double>();

			// 锚点的深度。
			var depth = (float)rect.Height * anchor.Y;

			// 获得锚点的具体位置。
			anchorPos = new Point()
			{
				X = (float)(rect.Width * anchor.X + rect.Left),
				Y = (float)(depth + rect.Top), // 获得锚点的纵坐标。
			};

			var len = (float)(depth + distance); // 旋转控点距离锚点的总距离。

			var rot = MathF.PI * 2 / 4;

			// 锚点距离控点的向量。
			var rotationEdge1Vec = new Vector2(0, len);
			rotationEdge1Vec = rotationEdge1Vec.SetRotation(rotation - rot);

			// 锚点距离边的距离。
			var rotationEdge2Vec = new Vector2(0, depth);
			rotationEdge2Vec = rotationEdge2Vec.SetRotation(rotation - rot);

			// 控点位置。
			rotationPos = anchorPos.Add(rotationEdge1Vec); // 控点的位置。
			onEdge = anchorPos.Add(rotationEdge2Vec); // 距离的交点。

			var v1 = rect.TopLeft.Sub(anchorPos);
			var v2 = rect.TopRight.Sub(anchorPos);
			var v3 = rect.BottomRight.Sub(anchorPos);
			var v4 = rect.BottomLeft.Sub(anchorPos);

			v1 = v1.IncreaseRotation(rotation);
			v2 = v2.IncreaseRotation(rotation);
			v3 = v3.IncreaseRotation(rotation);
			v4 = v4.IncreaseRotation(rotation);

			point1 = anchorPos.Add(v1);
			point2 = anchorPos.Add(v2);
			point3 = anchorPos.Add(v3);
			point4 = anchorPos.Add(v4);

			point12 = point1.Mid(point2);
			point23 = point2.Mid(point3);
			point34 = point3.Mid(point4);
			point41 = point4.Mid(point1);

			var arr = new[] { point1, point2, point3, point4 };

			foreach (var item in shape.Adjustments)
			{
				extra.Add(item.ToPixelValue() / Emu.Num100.ToPixelValue());
			}

			return new FrameInfo()
			{
				originLeft = rect.Left,
				originTop = rect.Top,
				width = rect.Width,
				height = rect.Height,
				point1 = point1,
				point2 = point2,
				point3 = point3,
				point4 = point4,
				point12 = point12,
				point23 = point23,
				point34 = point34,
				point41 = point41,
				anchor = anchorPos,
				rotationPos = rotationPos,
				rotation = rotation,
				onEdge = onEdge,
				extra = extra.ToArray(),
				left = Left(arr),
				right = Right(arr),
				top = Top(arr),
				buttom = Buttom(arr)

			};


		}




	}
}
